﻿using System;
using System.Collections;
using System.Diagnostics;
using System.Runtime.InteropServices;
using log4net;
using Microsoft.BizTalk.Component.Interop;
using Microsoft.BizTalk.Message.Interop;
using AppFx.BizTalk.Container;
using Autofac;
using AppFx.BizTalk.PipelineComponents.Spec;
using AppFx.BizTalk.Diagnostics;

namespace AppFx.BizTalk.PipelineComponents
{
    [ComponentCategory(CategoryTypes.CATID_PipelineComponent)]
    [ComponentCategory(CategoryTypes.CATID_Any)]
    [Guid(ComponentGuid)]
    public class RunContainerExtensions : BaseCustomPipelineComponent, IComponent, IComponentUI, IPersistPropertyBag, IBaseComponent
    {
        private static readonly ILog Log = LogFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
        private const string ComponentGuid = "3E2FB3BC-792F-4F1C-B1E4-09B4653F2FE5";
        private const string ComponentDescription = "Runs a set of extensions from the IOC container";
        private const string ComponentName = "Run Container Extensions";

        public RunContainerExtensions()
            : base(ComponentName, typeof(RunContainerExtensions), ComponentDescription)
        {

        }

        public IBaseMessage Execute(IPipelineContext pContext, IBaseMessage pInMsg)
        {
            if (string.IsNullOrEmpty(DelimitedExtensionKeys))
            {
                Log.Info("No container extensions have been specified");
                return pInMsg;
            }
            Log.DebugFormat("DelimitedExtensionKeys = {0}", DelimitedExtensionKeys);
            Log.DebugFormat("ContainerName = {0}", ContainerName);

            var container = new BizTalkApplicationContainer(ContainerName);

            var keys = DelimitedExtensionKeys.Split(',');
            if (keys.Length == 0) return pInMsg;
            foreach (var key in keys)
            {
                var extension = container.Container.ResolveNamed<IDefaultPipelineExtension>(key);
                if (extension == null)
                    Log.WarnFormat("Container Extension {0} was not found in the container", key);
                else
                    extension.Execute(pContext, pInMsg);
            }
            return pInMsg;
        }
       

        #region Component Properties
        private string _containerName;
        private string _delimitedExtensionKeys;

        public string DelimitedExtensionKeys
        {
            get { return _delimitedExtensionKeys; }
            set { _delimitedExtensionKeys = value; }
        }

        public string ContainerName
        {
            get { return _containerName; }
            set { _containerName = value; }
        }      
               

        #endregion

        public IntPtr Icon
        {
            get { return new IntPtr(); }
        }

        public IEnumerator Validate(object projectSystem)
        {
            return null;
        }

        // ReSharper disable once InconsistentNaming
        public void GetClassID(out Guid classID)
        {
            classID = new Guid(ComponentGuid);
        }

        public void InitNew()
        {
            //Do nothing
        }

        public void Load(IPropertyBag propertyBag, int errorLog)
        {
            try
            {
                base.ReadPropertyBag(propertyBag, "ContainerName", ref _containerName);
                base.ReadPropertyBag(propertyBag, "DelimitedExtensionKeys", ref _delimitedExtensionKeys);
            }
            catch (Exception ex)
            {
                Trace.WriteLine(ex.ToString());
                throw;
            }
        }

        public void Save(IPropertyBag propertyBag, bool clearDirty, bool saveAllProperties)
        {
            try
            {
                base.WritePropertyBag(propertyBag, "ContainerName", _containerName);
                base.WritePropertyBag(propertyBag, "DelimitedExtensionKeys", _delimitedExtensionKeys);                
            }
            catch (Exception ex)
            {
                Trace.WriteLine(ex.ToString());
                throw;
            }
        }



        public string Description
        {
            get { return ComponentDescription; }
        }

        public string Name
        {
            get { return ComponentName; }
        }

        public string Version
        {
            get { return GetType().Assembly.GetName().Version.ToString(); }
        }
    }
}






